1. Background and Relevant Art
As computerized systems have increased in popularity, so have the various application programs and documents used on the computerized systems. In particular, there are now a wide range of applications programs configured for any number of purposes, whether to function as complex operating systems, databases, and so forth, or to function as more simple application programs configured for a narrow purpose. In many cases, software developers will write new application programs with a particular operating system/framework in mind, using any number of appropriate programming languages. Once the software is complete, the developer will compile the application into code, which can then be installed on a computer system with the appropriate operating system. In many cases, operating the new application program will involve interoperation with several other components or applications in the system/framework.
One will appreciate, therefore, that there are a number of considerations that often must be taken into account by developers of operating systems or generalized frameworks as well as developers of the individual application programs operating within the framework. Many of these interests may even be competing. For example, many application program developers may have interests related to fast and customizable operation, while many operating system/framework developers may have interests related to security and stability. In some cases, the security and stability requirements can restrict the speed and customizability of the way some application programs operate.
One area in which this tension can be apparent is with certain kinds of “type frameworks.” In a type framework, functions, arguments, and even data values may be correlated with a specific “type,” which generally defines how various data (i.e., functions, arguments, or values) need to appear before another application or component can access/process the corresponding data. In a system employing a strong type framework, the framework may be configured so that applications or components using one type framework are prohibited from executing or accessing functions and data corresponding to other type frameworks. Some example frameworks include nominal (or nominative) and structural type frameworks, although there are may different kinds of type frameworks.
In general, nominal (or nominative) type frameworks are configured so that data in one nominal type can only access (or be accessed by) other data that use the exact same type names (are of the same nominal type), or otherwise access (be accessed by) type names it knows about at creation/compilation, and vice versa. Thus, one application that uses a type name called “customer record” might be prohibited from accessing similar data managed by another application program under a type name called “member record,” even though the type structure might be identical, if both types are unaware of each other. For example, structural identity might occur where both of the nominal types of customer record and member record include an equal number and kind of fields (e.g., a set including: first name=“string,” and second name=“string,” etc.) In contrast, structural type frameworks rely on matches between data structures or shapes, rather than names. While structural types are not limited to inexact type names, structural mismatches can occur when one of the types includes more or different kinds of structures/shapes than another type (e.g., member record includes first name=“string,” second name=“string,” and phone number=value).
Often, there are various workarounds to mismatches between various different types, including nominal and structural types so that applications can interoperate. Within a nominal type framework, for example, a developer can write new code for each application of interest that maps or converts type structures in one nominal type to identical type structures in another nominal type. Although a similar workaround between mismatched type structures is also possible, such conversion of structural types tends to be more complex. For example, the Lisp programming language implements one common, conventional structural type framework, where the basic structure is the data pair. To use data of another application program, therefore, a Lisp-based application will typically need to convert data structures in the other application into a data pair structure, which can be difficult.
Similarly, it can be difficult to convert from a Lisp data pair structure to another type structure in another application. This is true not only for differences in how data are arranged in Lisp, but also since the values of the Lisp data pair are often difficult to ascertain without a computationally expensive, complete traversal of the data pairs. This is partly because Lisp data pairs tend not to provide very much information via a basic query other than that the data pair are a “sequence.” The Lisp programming framework, however, is not the only language that can present problems with different type structures. Other common languages that each use their own different type frameworks include XML, SQL, .NET, and JAVA, and interoperation often means some type conversion.
Accordingly, one way of ensuring interoperability between application programs is for application developers working on a similar platform to agree in advance to the details of nominal and/or types, as applicable. Of course, such rigid and precise agreement is not always possible, and provides little flexibility for other developers who may create components that will be used in the same system at a later time. Thus, developers often end up trying (as previously described) to write one or more interfaces that convert or otherwise map data in newer application types to data in another application type. For example, a developer writing an application written in one type framework may need to write one adaptor for other applications written in the Lisp programming language, and/or potentially also a separate adaptor for applications written in each of the XML, SQL, .NET, and JAVA programming languages.
One will appreciate that this means that the developer of the new application program will need to know (or learn) about the types used in the other programs. With fewer applications to consider, this problem may be more of a minor inconvenience. More commonly, however, this kind of scenario becomes exponentially problematic for many developers, particularly as the number of application programs that use similar or identical kinds of data (e.g., membership records, functions, etc.) on a system can grow. This problem can be further exacerbated since each of the various application programs can change or go through various upgrades, which may result in still further changes in type names and/or structures.
Yet another way others have tried to solves these types of problem is with “loose” or dynamic typing. With loose or dynamic typing, a newer application program need not necessarily have a precise understanding of type names or structures in preexisting application programs. Rather, the application components can determine at runtime if there is complete match between type structures/shapes, then map those type shapes during runtime. Unfortunately, dynamic or loose typing does not solve the problem of what to do when items of interest are structurally similar but not identical. Furthermore, and perhaps more importantly, dynamic or loose typing tends to result in significant performance and security losses, due to the runtime examinations by the applications that tend not to be evident with strong, or nominal typing systems.
Accordingly, there are a number of difficulties associated with accessing and using functions or data in type frameworks that can be addressed.